package com.express.aop;

import com.alibaba.fastjson.JSONObject;
import com.express.po.ApiErrorLog;
import com.express.po.ApiLog;
import com.express.mongo.ApiLogsDao;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

/**
 * 日志切面
 */

@Aspect
@Component
public class LogWebAspect {

    @Autowired
    private MongoTemplate mongo;

    @Autowired
    private ApiLogsDao apiLogsDao;

    private static final Logger logger = LoggerFactory.getLogger(LogWebAspect.class);

    // 定义切点 Pointcut
    @Pointcut(value = "execution(* com.express.controller.*.*(..)))")//拦截路径
    public void LogPointcut() {
    }

    /**
     * 接口日志
     *
     * @param joinPoint
     * @param ret
     * @throws Throwable
     */
    @AfterReturning(returning = "ret", pointcut = "LogPointcut()")
    public void doAfterReturning(JoinPoint joinPoint, Object ret) throws Throwable {

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        //有格式的打印日志，收集日志信息到ES
        logger.info(System.currentTimeMillis() + "|" + request.getRequestURL().toString() + "|" + request.getMethod() + "|" +
                joinPoint.getSignature().getDeclaringTypeName() + "|" + Arrays.toString(joinPoint.getArgs()));
        // 记录下请求内容
        logger.info("=============请求开始================");
        long timeStamp = System.currentTimeMillis();
        logger.info("【TIME        】 : " + timeStamp);
        logger.info("【IP          】 : " + request.getRemoteAddr());
        logger.info("【URL         】 : " + request.getRequestURL().toString());
        logger.info("【HTTP_METHOD 】 : " + request.getMethod());
        logger.info("【CLASS_METHOD】 : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature
                ().getName());
        logger.info("【ARGS        】 : " + Arrays.toString(joinPoint.getArgs()));
        // 处理完请求，返回内容
        logger.info("【RESPONSE    】 : " + ret);
        logger.info("==============响应结束===============");
        ApiLog apiLog = new ApiLog();
        apiLog.setTimeStamp(timeStamp+"");
        apiLog.setIp(request.getRemoteAddr());
        apiLog.setUrl(request.getRequestURL().toString());
        apiLog.setHttpMethod(request.getMethod());
        apiLog.setMethodPath(joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        apiLog.setArgs(Arrays.toString(joinPoint.getArgs()));
        apiLog.setRespJson(ret.toString());

        Object json = JSONObject.toJSON(apiLog);
        String s = json.toString();
        mongo.insert(apiLog,"apiLogs");
    }


    /**
     * 异常拦截
     *
     * @return
     */
    @AfterThrowing(throwing = "ex", pointcut = "LogPointcut()")
    public void afterThrowable(JoinPoint joinPoint,Exception  ex) {

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        long timeStamp = System.currentTimeMillis();
        String ip = request.getRemoteAddr();
        String url = request.getRequestURL().toString();
        String method = request.getMethod();
        String typeName = joinPoint.getSignature().getDeclaringTypeName();
        String name = joinPoint.getSignature().getName();
        String PathName = typeName+ "." + name;
        String args = Arrays.toString(joinPoint.getArgs());
        logger.info("=============请求参数================");
        logger.info("【TIME        】 : " + timeStamp);
        logger.info("【IP          】 : " + ip);
        logger.info("【URL         】 : " + url);
        logger.info("【HTTP_METHOD 】 : " + method);
        logger.info("【CLASS_METHOD】 : " + PathName);
        logger.info("【ARGS        】 : " + args);
        logger.info("【EXCEPTION   】 : " + ex);
        logger.info("==============异常结束===============");
        ApiErrorLog apiErrorLog = new ApiErrorLog();
        apiErrorLog.setTimeStamp(timeStamp+ "");
        apiErrorLog.setIp(ip);
        apiErrorLog.setUrl(url);
        apiErrorLog.setHttpMethod(method);
        apiErrorLog.setMethodPath(PathName);
        apiErrorLog.setException(ex.toString());

        mongo.insert(apiErrorLog,"apiErrorLogs");
    }

}
